package com.tomek.ktoryoperator.tasks;

import java.util.Arrays;
import java.util.Map;

import android.content.ContentResolver;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import com.tomek.ktoryoperator.R;
import com.tomek.ktoryoperator.exceptions.NumberInfoProviderException;
import com.tomek.ktoryoperator.model.DBEntry;
import com.tomek.ktoryoperator.model.SingleEntry;
import com.tomek.ktoryoperator.providers.NumberInfoProvider;
import com.tomek.ktoryoperator.providers.ProvidersFactory;
import com.tomek.ktoryoperator.utils.ContentProvidersUtils;
import com.tomek.ktoryoperator.utils.LogUtils;
import com.tomek.ktoryoperator.utils.NotificationUtils;
import com.tomek.ktoryoperator.utils.PreferenceUtils;

public class GetInfoForNumberGUITask extends AsyncTask<SingleEntry, Void, String> {
	final Context context;
	final Map<String, NumberInfoProvider> numberInfoProviders;
	final EndTaskListener endTaskListener;

	private NumberInfoProviderException result;

	private boolean match;

	public GetInfoForNumberGUITask(Context context, Map<String, NumberInfoProvider> numberInfoProviders,
			EndTaskListener endTaskListener) {
		this.context = context;
		this.numberInfoProviders = numberInfoProviders;
		this.endTaskListener = endTaskListener;
	}

	@Override
	protected String doInBackground(SingleEntry... numbers) {
		LogUtils.d(getClass(), "doInBackground", "numbers=%s", Arrays.asList(numbers));

		SingleEntry se = numbers[0];
		String number = se.number;

		long currentTime = System.currentTimeMillis();

		for (NumberInfoProvider infoProvider : this.numberInfoProviders.values()) {
			try {
				if (infoProvider.canHandle(number)) {
					long timeout = infoProvider.getQueryTimeout();

					if (currentTime - se.date < timeout) {
						// too often query
						result = new NumberInfoProviderException(R.string.info_up_to_date_msg);
					} else {
						String numberInfoId = infoProvider.getNumberInfoId(number);

						if (numberInfoId != null) {
							saveAndNotify(number, numberInfoId, infoProvider.getProviderId());

							match = true;
							break;
						}
					}
				}
			} catch (NumberInfoProviderException e) {
				LogUtils.e(e, "Blad podczas odczytu danych o numerze");

				result = e;
			}
		}

		return number;
	}

	@Override
	protected void onPostExecute(String number) {
		if (endTaskListener != null) {
			endTaskListener.taskEnded(number);
		}

		if (result != null) {
			Toast.makeText(context, result.getResourceId(), Toast.LENGTH_LONG).show();
		} else {
			if (!match) {
				Toast.makeText(context, R.string.providers_no_match, Toast.LENGTH_LONG).show();
			}
		}
	}

	private void saveAndNotify(String number, String numberInfoId, String providerId) {
		LogUtils.d(getClass(), "saveAndNotify", "number=%s, numberInfoId=%s", number, numberInfoId);

		ContentResolver cr = this.context.getContentResolver();
		DBEntry entry = ContentProvidersUtils.load(cr, number);

		if (entry != null) {
			// jest wpis dla takiego numeru, update
			ContentProvidersUtils.updateEntry(cr, entry.id, providerId, numberInfoId);

			if (!entry.value.equals(numberInfoId) && PreferenceUtils.notifyAboutNetworkOperatorChange(context)) {
				String contactName = ContentProvidersUtils.getContactNameForNumber(cr, number);

				String value = ProvidersFactory.getInstance().getInfoProviders().get(providerId)
						.getNumberInfoName(context, numberInfoId);

				NotificationUtils.showNotificationOperatorChanged(context, contactName, number, entry.value, value);
			}
		} else {
			// nie ma takiego wpisu jeszcze, insert
			ContentProvidersUtils.insertEntry(cr, number, providerId, numberInfoId);

			if (PreferenceUtils.notifyAboutFirstRead(context)) {
				String contactName = ContentProvidersUtils.getContactNameForNumber(cr, number);

				String value = ProvidersFactory.getInstance().getInfoProviders().get(providerId)
						.getNumberInfoName(context, numberInfoId);
				NotificationUtils.showNotificationOperatorAdded(context, contactName, number, value);
			}
		}
	}

	public static interface EndTaskListener {
		public void taskEnded(String... numbers);
	}
}